package com.pine.dcts.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pine.dcts.common.DctsConstant;
import com.pine.dcts.entity.DatasourceInfo;
import com.pine.dcts.entity.Org;
import com.pine.dcts.mapper.DataBaseInfoMapper;
import com.pine.dcts.metadata.MetadataAnalysis;
import com.pine.dcts.model.DatasourceDTO;
import com.pine.dcts.model.Field;
import com.pine.dcts.model.OrgDTO;
import com.pine.dcts.model.Table;
import com.pine.dcts.service.DatasourceService;
import com.pine.dcts.service.OrgService;
import com.pine.dcts.utils.CopierUtil;
import com.pine.dcts.utils.TreeUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DatasourceServiceImpl extends ServiceImpl<DataBaseInfoMapper, DatasourceInfo> implements DatasourceService {
    @Autowired
    private OrgService orgService;

    @Override
    public List<OrgDTO> getDatasourceTree() {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Org::getStatus, DctsConstant.YES);
        List<Org> orgs = this.orgService.list(wrapper);
        return covert(TreeUtils.getTreeList(null, CopierUtil.copy(orgs, OrgDTO.class)));
    }

    @Override
    public List<String> getSchemasByDatasourceId(Integer datasourceId) {
        DatasourceInfo datasourceInfo = super.getById(datasourceId);
        MetadataAnalysis analysis = new MetadataAnalysis(datasourceInfo);
        return analysis.getAllSchemasByCateLog(datasourceInfo.getDb());
    }

    @Override
    public List<Table> getTablesByDatasourceId(Integer datasourceId,String schemaName) {
        DatasourceInfo datasourceInfo = super.getById(datasourceId);
        MetadataAnalysis analysis = new MetadataAnalysis(datasourceInfo);
        List<Table> tables = Lists.newArrayList();
        if(StringUtils.isNotEmpty(schemaName)){
            return analysis.getAllTableList(datasourceInfo.getDb(),schemaName);
        }
        List<String> schemas =   analysis.getAllSchemasByCateLog(datasourceInfo.getDb());
        if(CollectionUtils.isNotEmpty(schemas)){
            analysis.getAllSchemasByCateLog(datasourceInfo.getDb()).forEach(str -> {
                tables.addAll(analysis.getAllTableList(datasourceInfo.getDb(), str));
            });
            return tables;
        }
        return analysis.getAllTableList(datasourceInfo.getDb(),null);
    }

    @Override
    public List<Field> getFieldsByTable(Integer datasourceId, String schemaName,String tableName) {
        DatasourceInfo datasourceInfo = super.getById(datasourceId);
        MetadataAnalysis analysis = new MetadataAnalysis(datasourceInfo);
        return analysis.getTableColumns(datasourceInfo.getDb(),schemaName,tableName);
    }


    private List<OrgDTO> covert(List<OrgDTO> orgDTOS) {
        Map<Integer, List<DatasourceDTO>> machineMap = CopierUtil.copy(this.list(), DatasourceDTO.class).stream().collect(
                Collectors.groupingBy(e -> e.getOrgId()));
        querySubTree(orgDTOS, machineMap);
        return orgDTOS;
    }

    private void querySubTree(List<OrgDTO> orgDTOS, Map<Integer, List<DatasourceDTO>> datasourceMap) {
        orgDTOS.forEach(orgDTO -> {
            if (CollectionUtils.isEmpty(orgDTO.getChildren())) {
                orgDTO.setDatasources(datasourceMap.get(orgDTO.getId()));
            }
            if (CollectionUtils.isNotEmpty(orgDTO.getChildren())) {
                querySubTree(orgDTO.getChildren(), datasourceMap);
            }
        });
    }

    @Override
    public DatasourceInfo getById(Serializable id) {
        return super.getById(id);
    }
}
